<?php
// $Id: Item.interface.php 73 2007-02-12 03:45:43Z tswicegood $

/**
 * This file contains {@link Item} which is part of the PHP Content Repository
 * (phpCR), a derivative of the Java Content Repository JSR-170,  and is 
 * licensed under the Apache License, Version 2.0.
 *
 * This file is based on the code created for
 * {@link http://www.jcp.org/en/jsr/detail?id=170 JSR-170}
 *
 * @author Travis Swicegood <travis@domain51.net>
 * @copyright PHP Code Copyright &copy; 2004-2005, Domain51, United States
 * @copyright Original Java and Documentation 
 *  Copyright &copy; 2002-2004, Day Management AG, Switerland
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, 
 *      Version 2.0
 * @package phpContentRepository
 */


/**
 * Load the {@link phpCR} library file(s)
 */ 
require_once(dirname(__FILE__) . '/phpCR.library.php');


if (phpCR::getLevel() >= 2) {
    phpCR::loadInterface('Lock', '/lock');
}


/**
 * {@link Item} is the base interface of {@link Node} and {@link Property}.
 *
 * @see Node, Property
 * @author PHP - Travis Swicegood <travis@domain51.net>
 * @copyright Copyright &copy; 2004-2005, Domain51
 * @package phpContentRepository
 */
interface Item
{
   /**
    * Returns the path to this {@link Item}.
    *
    * If this {@link Item} or an ancestor has multiple parents then this 
    * {@link Item} will have more than one path.  In that case, this method 
    * returns one of those paths. The mechanism by which the implementation 
    * chooses which path to return is left unspecified, the only requirement 
    * being that for a given {@link Item} this method always returns the same 
    * path.  
    *
    * To get all paths to this {@link Item} use {@link getPaths()}.
    *
    * @see getPaths()
    * @return string 
    *  The path (or one of the paths) of this {@link Item}.
    */
    public function getPath();
    
    
   /**
    * Returns all paths to this {@link Item}.
    *
    * To retrieve a single path for this {@link Item} use {@link getPath()}.
    *
    * @see getPath()
    * @return array
    *   An array of strings: all paths that lead to this {@link Item}.
    */
    public function getPaths();
    
    
   /**
    * Returns the name of this {@link Item}.
    *
    * The name is the last {@link Item} in the path. If this {@link Item}
    * is the root node of the repository (i.e. if 
    * this.getDepth() == 0), an empty string will be returned.
    *
    * If this {@link Item} has multple paths then the name returned is the last
    * {@link Item} in the path returned by {@link getPath()}.
    *
    * @return string
    *   The (or a) name of this {@link Item} or an empty string if this 
    *   {@link Item} is the root {@link Node}.
    */
    public function getName();
    
    
   /**
    * Returns the ancestor of the specified absolute degree.
    *
    * An ancestor of absolute degree x is the {@link Item} that is 
    * x levels down along the path from the root node to 
    * $this {@link Item}.
    *
    * <ul>
    *   <li>$degree = 0 returns the root node.</li>
    *   <li>$degree = 1 returns the child of the root node along 
    *       the path to $this {@link Item}.
    *   <li>$degree = 2 returns the grandchild of the root node 
    *       along the path to $this {@link Item}.
    *   <li>And so on to $degree = n, where n is
    *       the depth of $this {@link Item}, which returns 
    *       $this {@link Item} itself.
    * </ul>
    *
    * If $degree &gt; n is specified then a 
    * {@link ItemNotFoundException} is thrown.
    *
    * If multiple paths exist to this {@link Item} then the path used is the 
    * same one that is returned by {@link getPath()}.
    *
    * @param int
    *   An integer, 0 &lt;= $degree &lt;= n where 
    *   n is the depth of $this {@link Item} along the
    *   path returned by {@link getPath()}.
    * @return object
    *   The ancestor of the specified absolute degree of $this
    *   {@link Item} along the path returned by{@link getPath()}.
    *
    * @throws {@link ItemNotFoundException}
    *   If $degree &lt; 0 or $degree &gt; n
    *   where n is the is the depth of $this {@link Item}
    *   along the path returned by {@link getPath()}.
    * @throws {@link AccessDeniedException}
    *   If the current {@link Ticket} does not have sufficient access rights to
    *   complete the operation.
    * @throws {@link RepositoryException}
    *   If another error occurs.
    */
    public function getAncestor($degree);
    
    
   /**
    * Returns the parent of this {@link Item}.
    *
    * If this {@link Item} has multiple paths then this method returns the
    * parent along the path returned by {@link getPath()}.
    *
    * @return object
    *   The parent of this {@link Item} along the path returned by 
    *   {@link getPath()}.
    *
    * @throws {@link ItemNotFoundException}
    *   If there is no parent.  This only happens if $this 
    *   {@link Item} is the root node.
    * @throws {@link AccessDeniedException}
    *   If the current {@link Ticket} does not have sufficient access rights to
    *   complete the operation.
    * @throws {@link RepositoryException}
    *   If another error occurs.
    */
    public function getParent();
    
    
   /**
    * Returns all parents of this {@link Item} in a {@link NodeIterator}.
    *
    * @return object
    *   A {@link NodeIterator} over the parents of this {@link Item}.
    *
    * @throws {@link ItemNotFoundException}
    *   If there is no parent. This only happens if $this 
    *   {@link Item} is the root.
    * @throws {@link AccessDeniedException}
    *   If the current {@link Ticket} does not have sufficient access rights to
    *   complete the operation.
    * @throws {@link RepositoryException}
    *   If another error occurs.
    */
    public function getParents();
    
    
   /**
    * Returns the {@link Ticket} through which this {@link Item} was acquired.
    *
    * Every {@link Item} can ultimately be traced back through a series of
    * method calls to the call {@link Ticket::getRootNode()}, 
    * {@link Ticket::getNodeByAbsPath()} or {@link Ticket::getNodeByUUID()}. 
    * This method returns that {@link Ticket} object.
    *
    * @return object
    *   The {@link Ticket} through which this {@link Item} was acquired.
    */
    public function getTicket();
    
    
   /**
    * Accepts an {@link ItemVisitor}.
    *
    * @param object
    *   The {@link ItemVisitor} to be accepted.
    *
    * @throws {@link RepositoryException} 
    *   If an error occurs.
    */
    public function accept(ItemVisitor $visitor);
    
    
   /**
    * Indicates whether this {@link Item} is a {@link Node} or a 
    * {@link Property}.
    * 
    * @return bool 
    *   Returns TRUE if this {@link Item} is a {@link Node};
    *   Returns FALSE if this {@link Item} is a {@link Property}.
    */
    public function isNode();
    
    
   /**
    * Returns the status of this {@link Item} regarding the specified 
    * {@link Permission}s.
    *
    * Returns the status of this {@link Item} regarding the specified 
    * $permissions (under the rights held by current 
    * {@link Ticket}).  See {@link Permission} and 
    * {@link AccessManager} for more details. Equivalent to:
    *
    * $AccessManager->isGranted($this, $permissions).
    *
    * @see AccessManager, Permission
    * @param int
    *   A combination of one or more of the following constants encoded as a
    *   bitmask value:
    *   <ul>
    *       <li>Permission::ADD_NODE</li>
    *       <li>Permission::SET_PROPERTY</li>
    *       <li>Permission::REMOVE_ITEM</li>
    *       <li>Permission::READ_ITEM</li>
    *   </ul>
    * @return bool
    *   TRUE if all requested permissions are true for this
    *   {@link Item}; FALSE otherwise.
    * @throws {@link UnsupportedRepositoryOperationException}
    *   If access control discovery is not supported.
    * @throws {@link RepositoryException}
    *   If another error occurs.
    */
    public function isGranted($permissions);
    
    
   /**
    * Returns the depth of this {@link Item} in the repository tree.
    *
    * Returns the depth below the root node of $this {@link Item}
    * (counting $this {@link Item} itself).
    *
    * <ul>
    *   <li>The root {@link Node} returns 0.</li>
    *   <li>A property or child {@link Node} of the root {@link Node} 
    *       returns 1.</li>
    *   <li>A property or child {@link Node} of a child {@link Node} of the 
    *       root returns 2.</li>
    *   <li>And so on to $this {@link Item}.</li>
    * </ul>
    *
    * If multiple paths exist to this {@link Item} then the path used to 
    * determine the depth is the same one that is returned by {@link getPath()}.
    *
    * @return int
    *   The depth of this {@link Item} in the repository hierarchy.
    */
    public function getDepth();
    
    
   /**
    * Places a lock on this node, or throws an
    * {@link UnsupportedRepositoryOperationException} if locking is not
    * supported.
    *
    * Puts a lock on this item.
    *
    * The lock is of the specified $lockType. This standard defines 
    * only one type, {@link LockType::WRITE_LOCK}, though more can be added by
    * the implementation, see {@link LockType} for the semantics specific to 
    * this lock type.
    *
    * <b>General points about locking</b>
    *
    * Locking is an optional part of the specification. If locking is not
    * supported then this method will throw an
    * {@link UnsupportedRepositoryOperationException}, even in a level 2
    * implementation.
    *
    * Even if locking is supported, the features of a particular  implementation 
    * can vary along the following dimensions:
    *
    * <dl>
    *   <dt>Lock Type</dt>
    *   <dd>Only {@link LockType::WRITE_LOCK} is defined by this standard. An
    *       implementation may define other lock types.</dd>
    *   <dt>Lock Scope</dt>
    *   <dd>An implementation may choose to implement exclusive locks, shared
    *       locks or both.</dd>
    *   <dt>Lock Level</dt>
    *   <dd>An implementation may choose to implement locking on {@link Node}s
    *       only or on both {@link Node}s and {@link Property}s. If the 
    *       implementation locks only on the {@link Node} level this is 
    *       equivalent to a "both {@link Node}s and {@link Property}s" locking 
    *       implementaion in which locking or unlocking a {@link Node} 
    *       automatically performs the same operation on all its 
    *       {@link Property}s.</dd>
    * </dl>
    *
    * Information about what locking support is provided is available via the
    * method {@link Workspace::getLockCapabilities()} which returns a
    * {@link LockCapabilities} object which provides methods for querying the 
    * locking support provided by the implementation.
    *
    * @see Workspace::getLockCapabilities()
    * @param bool
    *   If TRUE set locks on all descendants also.
    *
    * @param bool
    *   Whether the {@link Lock} is shared or exclusive
    *
    * @param lockType The type of the lock
    *
    * @return The Lock object.
    *
    * @throws {@link AccessDeniedException}
    *   If the user {@link Ticket} does not have the right to {@link Lock} this
    *   user or does have the right to {@link Lock} this 
    *   {@link Node} but an exclusive {@link Lock} is already held by another 
    *   user.
    * @throws {@link UnsupportedRepositoryOperationException}
    *   If the $lockType or $shared status is not 
    *   supported in this implementation or locking in general is not supported.
    * @throws {@link RepositoryException}
    *   If another error occurs.
    */
    public function lock($recurse, $shared, $lockType);
    
    
   /**
    * Removes the specified $lock from this {@link Node} or 
    * throws an {@link UnsupportedRepositoryOperationException} if locking is
    * not supported.
    *
    * If this {@link Node} is not locked, then this method has no effect.
    * 
    * If this {@link Node} is locked and the user of this {@link Ticket} is a 
    * user of the lock then the lock is removed.  If this {@link Node} is
    * locked but the user of this {@link Ticket} does not have the power to 
    * unlock it, then an {@link AccessDeniedException} is thrown.
    *
    * @throws {@link AccessDeniedException}
    *   In level 1: Never.
    *   In level 2: If the user of this {@link Ticket} does not have the right 
    *   to unlock this {@link Node}.
    * @throws {@link UnsupportedRepositoryOperationException}
    *   If locking in general is not supported.
    */
    public function unlock(Lock $lock);
    
    
   /**
    * Returns all locks on this {@link Node} or throws an
    * {@link UnsupportedRepositoryOperationException} if locking is not
    * supported.
    *
    * Returns all {@link Lock}s on this {@link Node}, if there are any,
    * otherwise returns NULL.
    *
    * @return The {@link Lock}s on $this {@link Node}
    *
    * @throws {@link UnsupportedRepositoryOperationException}
    *   If locking in general is not supported.
    */
    public function getLocks();
    
    
   /**
    * Returns TRUE if there is a lock on this node, 
    * FALSE otherwise.
    *
    * @return bool
    */
    public function hasLocks();
    
    
   /**
    * Returns TRUE if $this {@link Item} represents 
    * the same repository {@link Item} as the object $otherItem.
    *
    * @param object
    *   The {@link Item} to be tested for identity with $this.
    * @return bool
    */
    public function isIdentical(Item $otherItem);
}
